package logger

import (
	"go.uber.org/zap"
)

type Pair struct {
	Key   string
	Value interface{}
}

type Pairs []Pair

type Logger struct {
	base    *zap.SugaredLogger
	traceID string
}

func New() *Logger {
	return &Logger{
		base: zapLogger.WithOptions(zap.AddCaller(), zap.AddCallerSkip(1)).Sugar(),
	}
}

func (l *Logger) Debug(v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Debug(v...)
}

func (l *Logger) Debugf(format string, v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Debugf(format, v...)
}

func (l *Logger) Info(v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Info(v...)
}

func (l *Logger) Infof(format string, v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Infof(format, v...)
}

func (l *Logger) Warn(v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Warn(v...)
}

func (l *Logger) Warnf(format string, v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Warnf(format, v...)
}

func (l *Logger) Error(v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Error(v...)
}

func (l *Logger) Errorf(format string, v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Errorf(format, v...)
}

func (l *Logger) Fatal(v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Fatal(v...)
}

func (l *Logger) Fatalf(format string, v ...interface{}) {
	l.base.With(zap.String("traceId", l.traceID)).Fatalf(format, v...)
}

func (l *Logger) Trace(tag string, pairs Pairs) {
	fields := []interface{}{zap.String("traceId", l.traceID)}
	for _, pair := range pairs {
		fields = append(fields, zap.Any(pair.Key, pair.Value))
	}
	l.base.With(fields...).Info(tag)
}

func (l *Logger) SetTraceID(str string) {
	l.traceID = str
}

func (l *Logger) GetTraceID() string {
	return l.traceID
}
